package utfpr.gang5.hermes.controledepresenca.rmi;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.firebirdsql.jdbc.FBSQLException;
import org.hibernate.classic.Session;

import utfpr.gang5.hermes.controledepresenca.Factory;
import utfpr.gang5.hermes.controledepresenca.pojo.Aluno;
import utfpr.gang5.hermes.controledepresenca.pojo.Disciplina;
import utfpr.gang5.hermes.controledepresenca.pojo.Presenca;
import utfpr.gang5.hermes.controledepresenca.pojo.Professor;
import utfpr.gang5.hermes.controledepresenca.services.AlunoService;
import utfpr.gang5.hermes.controledepresenca.services.ProfessorService;
import utfpr.gang5.hermes.controledepresenca.util.HibernateUtil;

public class ControlePresencaServiceImpl extends UnicastRemoteObject implements
		ControlePresencaService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	private Map<Aluno, Integer> presencas;
	private List<Aluno> alunosList;

	private Thread thread;

	protected ControlePresencaServiceImpl() throws RemoteException {
		super();
		presencas = new HashMap<Aluno, Integer>();
		alunosList = new ArrayList<Aluno>();

		thread = new Thread() {
			public void run() {
				Calendar aula1 = Calendar.getInstance();
				aula1.set(Calendar.HOUR_OF_DAY, 8);
				aula1.set(Calendar.MINUTE, 20);
				aula1.set(Calendar.MILLISECOND, 0);

				Calendar aula2 = Calendar.getInstance();
				aula2.set(Calendar.HOUR_OF_DAY, 9);
				aula2.set(Calendar.MINUTE, 10);
				aula2.set(Calendar.MILLISECOND, 0);

				Calendar aula3 = Calendar.getInstance();
				aula3.set(Calendar.HOUR_OF_DAY, 10);
				aula3.set(Calendar.MINUTE, 0);
				aula3.set(Calendar.MILLISECOND, 0);

				Calendar aula4 = Calendar.getInstance();
				aula4.set(Calendar.HOUR_OF_DAY, 11);
				aula4.set(Calendar.MINUTE, 5);
				aula4.set(Calendar.MILLISECOND, 0);

				Calendar aula5 = Calendar.getInstance();
				aula5.set(Calendar.HOUR_OF_DAY, 12);
				aula5.set(Calendar.MINUTE, 0);
				aula5.set(Calendar.MILLISECOND, 0);

				Calendar agora = Calendar.getInstance();
				agora.set(Calendar.MILLISECOND, 0);

				if (agora.getTimeInMillis() == aula1.getTimeInMillis()
						|| agora.getTimeInMillis() == aula2.getTimeInMillis()
						|| agora.getTimeInMillis() == aula3.getTimeInMillis()
						|| agora.getTimeInMillis() == aula4.getTimeInMillis()
						|| agora.getTimeInMillis() == aula5.getTimeInMillis()) {

					for (Aluno a : presencas.keySet())
						presencas.put(a, 0);

				}
				
				try {
					sleep(1000 * 60);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			};
		};
		thread.start();
	}
	
	@Override
	protected void finalize() throws Throwable {
		if (thread != null && thread.isAlive())
			thread.stop();
		
		super.finalize();
	}

	private boolean isUniqueException(Exception e) {
		Throwable cause = e.getCause();
		if (cause == null)
			return false;

		if (cause instanceof FBSQLException) {
			return ((FBSQLException) cause).getErrorCode() == 335544665;
		}

		return false;
	}

	@Override
	public Status salvarProfessor(Professor professor) throws RemoteException {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		try {
			ProfessorService service = Factory.getProfessorService();
			service.salvar(professor);
			session.getTransaction().commit();
			return new Status(true, null);
		} catch (Exception e) {
			session.getTransaction().rollback();
			String msgErro = null;
			if (isUniqueException(e)) {
				msgErro = "Já existe um usuário cadastrado com este login";
			} else {
				msgErro = e.getCause() != null ? e.getCause().getMessage() : e
						.getMessage();
			}
			return new Status(false, msgErro);
		} finally {
			if (session.isOpen())
				session.close();
		}

	}

	@Override
	public Object login(String login, String senha) throws RemoteException {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		try {
			// UsuarioService daoUsuario = Factory.getUsuarioService();
			// Usuario usuario = daoUsuario.buscarPorUsername(login);
			// if (usuario != null)
			// return usuario;

			AlunoService daoAluno = Factory.getAlunoService();
			Aluno aluno = daoAluno.buscarPorUsername(login);
			if (aluno != null) {
				if (aluno.getSenha().equals(senha))
					return aluno;
			}

			// ProfessorService daoProf = Factory.getProfessorService();
			// Professor professor = daoProf.buscarPorUsername(login);
			// if (professor != null)
			// return professor;

		} catch (Exception e) {
			// String msgErro = null;
			// if (isUniqueException(e)) {
			// msgErro = "Já existe um usuário cadastrado com este login";
			// } else {
			// msgErro = e.getCause() != null ? e.getCause().getMessage() :
			// e.getMessage();
			// }
			return null;
		} finally {
			if (session.isOpen())
				session.close();
		}

		return null;
	}

	@Override
	public Disciplina buscarDisciplinaAtual(Aluno aluno) throws RemoteException {
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		try {
			Disciplina disciplina = Factory.getCalendarioSemanalService()
					.buscarDisciplinaAtual(aluno);
			return disciplina;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		} finally {
			if (session.isOpen())
				session.close();
		}

	}

	@Override
	public boolean verificarPresenca(Aluno aluno) throws RemoteException {
		if (!presencas.containsKey(aluno)) {
			presencas.put(aluno, 0);
			alunosList.add(aluno);
		}

		Integer count = presencas.get(aluno);
		count++;
		boolean presente = false;
		if (count >= 40) {
			Session session = HibernateUtil.getSessionFactory()
					.getCurrentSession();
			session.beginTransaction();
			try {
				
				Disciplina disciplina = Factory.getCalendarioSemanalService()
						.buscarDisciplinaAtual(aluno);

				Presenca presenca = new Presenca();
				presenca.setAluno(aluno);
				presenca.setDia(Calendar.getInstance());
				presenca.setDisciplina(disciplina);
				presenca.setPresente(true);
				Factory.getPresencaService().salvar(presenca);
				presente = true;
				
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				if (session.isOpen())
					session.close();
			}
			
		}
	
		presencas.put(aluno, count);

		return presente;
	}

	@Override
	public List<AlunoPresenca> monitorarPresencas() throws RemoteException {
		if (alunosList == null)
			return null;

		ArrayList<AlunoPresenca> list = new ArrayList<AlunoPresenca>();
		for (Aluno aluno : alunosList) {
			Disciplina disciplina = buscarDisciplinaAtual(aluno);
			Integer count = presencas.get(aluno);
			list.add(new AlunoPresenca(aluno, disciplina, count, count >= 40));
		}

		return list;
	}

}
